#include "cxidatetimepicker_p.h"
#include "common/logger/logger.h"
#include <QDate>
#include <QGuiApplication>
#include <QScreen>
#include <QWheelEvent>
#include <common/datetimeparser/datetimeparser.h>
#include <optional>
#include <qdesktopwidget.h>
CxiDateTimePickerPrivate::CxiDateTimePickerPrivate(CxiDateTimePicker* p)
	: QObject(p),
	  q_ptr(p),
	  m_currentSection(CxiDateTimePicker::DateTimeSection::None),
	  m_calendarPopupEnabled(true),
	  m_mainLayout(nullptr),
	  m_dropDownBtn(nullptr),
	  m_calendarWidget(nullptr)
{
}
CxiDateTimePickerPrivate::~CxiDateTimePickerPrivate() = default;
//初始化lineedit
void CxiDateTimePickerPrivate::init()
{
	// 初始化主布局（LineEdit+按钮）
	m_mainLayout = new QHBoxLayout(q_ptr);
	m_mainLayout->setContentsMargins(0, 0, 0, 0);// 消除布局边距
	m_mainLayout->setSpacing(0);
	q_ptr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

	// 初始化下拉按钮
	initDropDownButton();
	// 初始化日历弹窗
	initCalendarWidget();

	m_format = "yyyy-MM-dd HH:mm";
	connect(q_ptr, &QLineEdit::editingFinished, this, &CxiDateTimePickerPrivate::validateInput);
}
//初始化下拉按钮
void CxiDateTimePickerPrivate::initDropDownButton()
{
	m_dropDownBtn = new QPushButton(q_ptr);

	QIcon icon;
	icon.addPixmap(QPixmap(":/icon/cmb.png"), QIcon::Normal);
	m_dropDownBtn->setIcon(icon);
	m_dropDownBtn->setIconSize(QSize(16, 16));
	m_dropDownBtn->setFlat(true);
	m_dropDownBtn->setFocusPolicy(Qt::NoFocus);
	// 设置固定宽度
	m_dropDownBtn->setFixedWidth(24);
	m_dropDownBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
	m_mainLayout->addStretch();
	m_mainLayout->addWidget(m_dropDownBtn);
	connect(m_dropDownBtn, &QPushButton::clicked, this, &CxiDateTimePickerPrivate::onDropDownButtonClicked);
}
//初始化日历弹窗
void CxiDateTimePickerPrivate::initCalendarWidget()
{
	m_calendarWidget = new CxiCalendarWidget(q_ptr);
	m_calendarWidget->setWindowFlags(Qt::Popup);
	m_calendarWidget->setHidden(true);
	connect(m_calendarWidget, &CxiCalendarWidget::signalSetCalendarTime, this, &CxiDateTimePickerPrivate::onCalendarDateSelected);
}
//计算日历弹窗的显示位置
QRect CxiDateTimePickerPrivate::calculateCalendarRect()
{
	if (!q_ptr || !m_calendarWidget)
	{
		return {};
	}

	// 1. 获取 q_ptr 在屏幕上的位置（全局坐标）
	QRect localRect = q_ptr->rect();
	QPoint globalTopLeft = q_ptr->mapToGlobal(localRect.topLeft());
	QRect editRect(globalTopLeft, localRect.size());

	// 2. 日历弹窗大小
	QSize calendarSize = m_calendarWidget->sizeHint();
	if (calendarSize.isEmpty())
	{
		calendarSize = QSize(200, 180);// 提供默认大小
	}

	// 3. 初始位置：LineEdit 下方，左对齐
	int x = editRect.left();
	int y = editRect.bottom();

	// 4. 获取当前屏幕的可用区域（排除任务栏）
	QScreen* screen = QGuiApplication::screenAt(editRect.center());
	if (!screen)
	{
		screen = QGuiApplication::primaryScreen();
	}
	QRect screenRect = screen->availableGeometry();

	// 5. 防止超出右侧
	if (x + calendarSize.width() > screenRect.right())
	{
		x = screenRect.right() - calendarSize.width();
	}

	// 6. 防止超出底部：如果下方不够，显示在上方
	if (y + calendarSize.height() > screenRect.bottom())
	{
		y = editRect.top() - calendarSize.height();// 显示在控件上方
	}

	return {x, y, calendarSize.width(), calendarSize.height()};
}


//处理鼠标点击事件
void CxiDateTimePickerPrivate::handleMousePressEvent(QMouseEvent* event)
{
	// 根据光标位置获取当前Section
	m_currentSection = sectionAtCursor();
	// 选中当前Section的文本
	selectCurrentSection();
}
//处理滚轮事件
void CxiDateTimePickerPrivate::handleWheelEvent(QWheelEvent* event)
{
	if (m_currentSection == CxiDateTimePicker::DateTimeSection::None)
	{
		m_currentSection = sectionAtCursor();
	}
	if (m_currentSection == CxiDateTimePicker::DateTimeSection::None)
	{
		event->ignore();
		return;
	}
	// 滑轮方向：上滚+1，下滚-1
	//	LOG_INFO("此时滚轮：" + section2String(m_currentSection));
	int delta = event->angleDelta().y() > 0 ? 1 : -1;
	adjustSectionValue(m_currentSection, delta);
	event->accept();
}
//处理按键事件
bool CxiDateTimePickerPrivate::handleKeyPressEvent(QKeyEvent* event)
{
	if (m_currentSection == CxiDateTimePicker::DateTimeSection::None)
	{
		m_currentSection = sectionAtCursor();
	}
	if (m_currentSection == CxiDateTimePicker::DateTimeSection::None)
	{
		event->ignore();
		return false;
	}
	// 处理上下箭头键
	if (event->key() == Qt::Key_Up)
	{
		adjustSectionValue(m_currentSection, 1);// 上箭头增加
		return true;
	}
	else if (event->key() == Qt::Key_Down)
	{
		adjustSectionValue(m_currentSection, -1);// 下箭头减少
		return true;
	}
	// 处理左右箭头键切换分段
	else if (event->key() == Qt::Key_Right)
	{
		moveToNextSection();// 右箭头移动到下一个分段
		return true;
	}
	else if (event->key() == Qt::Key_Left)
	{
		moveToPreviousSection();// 左箭头移动到上一个分段
		return true;
	}
	// 其他键不处理，交给父类
	return false;
}


//get/set
//设置显示格式
void CxiDateTimePickerPrivate::setDisplayFormat(const QString& format)
{
	m_format = sanitizeFormat(format);
	parseSections();
	if (m_sections.isEmpty())
	{
		m_format = "yyyy-MM-dd HH:mm";
		parseSections();
	}
}
bool CxiDateTimePickerPrivate::calendarPopup() const
{
	return m_calendarPopupEnabled;
}
void CxiDateTimePickerPrivate::setCalendarPopup(bool enable)
{
	m_calendarPopupEnabled = enable;
	if (m_dropDownBtn)
	{
		// 启用日历弹窗 → 显示按钮；禁用 → 隐藏按钮
		m_dropDownBtn->setVisible(enable);

		// 隐藏按钮时，同步隐藏日历
		if (m_calendarWidget && !enable)
		{
			m_calendarWidget->hide();
		}
	}
}
void CxiDateTimePickerPrivate::setDateTime(const std::optional<QDateTime>& dateTime)
{
	if (!dateTime)
	{
		q_ptr->setText("");
		return;
	}
	if (!dateTime.value().isValid())
	{
		q_ptr->setText("");
		return;
	}
	// 更新显示文本
	m_validText = dateTime.value().toString(m_format);
	q_ptr->setText(m_validText);
	//进入输入判断
	validateInput();
}
std::optional<QDateTime> CxiDateTimePickerPrivate::dateTime() const
{
	//	LOG_INFO("当前时间：" + q_ptr->text());
	//	LOG_INFO("当前时间：", QDateTime::fromString(q_ptr->text(), m_format).toString(m_format));
	if (q_ptr->text().isEmpty())
	{
		return std::nullopt;
	}
	return QDateTime::fromString(q_ptr->text(), m_format);
}


//槽函数
void CxiDateTimePickerPrivate::onDropDownButtonClicked()
{
	if (!m_calendarPopupEnabled || !m_calendarWidget)
	{
		return;
	}

	// 切换日历显示状态
	if (m_calendarWidget->isHidden())
	{
		// 更新日历选中日期为当前LineEdit的日期
		auto currentDt = dateTime();
		if (currentDt != std::nullopt)
		{
			m_calendarWidget->setSelectedDate(currentDt.value().date());
		}
		else
		{
			m_calendarWidget->setSelectedDate({});
		}
		// 计算弹窗位置（对齐LineEdit底部）
		m_calendarWidget->setGeometry(calculateCalendarRect());
		// 显示日历
		m_calendarWidget->show();
	}
	else
	{
		// 隐藏日历
		m_calendarWidget->hide();
	}
}
void CxiDateTimePickerPrivate::onCalendarDateSelected(const QDateTime& date)
{
	if (!m_calendarWidget)
	{
		return;
	}
	auto currentDt = dateTime();// 获取当前DateTimePicker的时间
	QDateTime newDt;
	if (currentDt != std::nullopt)
	{
		newDt = QDateTime(date.date(), currentDt.value().time());// 新日期+旧时间
	}
	else
	{
		newDt = QDateTime(date.date(), {});
	}

	setDateTime(newDt);

	m_calendarWidget->hide();
}

//工具函数
//移动到前一个分段
void CxiDateTimePickerPrivate::moveToPreviousSection()
{
	if (m_sections.isEmpty()) return;
	// 找到当前分段的索引
	int currentIndex = -1;
	for (int i = 0; i < m_sections.size(); ++i)
	{
		if (m_sections[i].type == m_currentSection)
		{
			currentIndex = i;
			break;
		}
	}
	// 计算上一个分段索引（循环）
	int prevIndex = (currentIndex - 1 + m_sections.size()) % m_sections.size();
	m_currentSection = m_sections[prevIndex].type;
	selectCurrentSection();
}
//移动到下一个分段
void CxiDateTimePickerPrivate::moveToNextSection()
{
	if (m_sections.isEmpty()) return;
	// 找到当前分段的索引
	int currentIndex = -1;
	for (int i = 0; i < m_sections.size(); ++i)
	{
		if (m_sections[i].type == m_currentSection)
		{
			currentIndex = i;
			break;
		}
	}
	// 计算下一个分段索引（循环）
	int nextIndex = (currentIndex + 1) % m_sections.size();
	m_currentSection = m_sections[nextIndex].type;
	selectCurrentSection();
}
//验证的Format
QString CxiDateTimePickerPrivate::sanitizeFormat(const QString& format)
{
	QString result;
	int i = 0;
	while (i < format.length())
	{
		QChar c = format[i];
		// 检查是否为合法的时间占位符开头
		if (c == 'y' || c == 'M' || c == 'd' || c == 'H' || c == 'h' || c == 'm' || c == 's')
		{
			// 匹配连续的相同字符（如 yyyy, MM, dd）
			int j = i;
			while (j < format.length() && format[j] == c)
				j++;

			int len = j - i;
			result += QString(len, c);// 保留合法占位符
			i = j;
		}
		else
		{
			// 非法字符（如 b, c）→ 直接跳过，不加入 result
			// 或者：如果你想保留分隔符（如 -, :, 空格），可以加白名单
			if (c.isSpace() || c == '-' || c == ':' || c == '/' || c == ' ' || c == '.')
			{
				result += c;// 保留常见分隔符
			}
			// 其他非法字母（如 b, c, x）→ 跳过
			i++;
		}
	}
	return result;
}
//初始化分段
void CxiDateTimePickerPrivate::parseSections()
{
	m_sections.clear();
	QRegExp yearRx("y+");   // 匹配年份（yyyy）
	QRegExp monthRx("M+");  // 匹配月份（MM）
	QRegExp dayRx("d+");    // 匹配日期（dd）
	QRegExp hourRx("H+|h+");// 匹配小时（HH或hh）
	QRegExp minuteRx("m+"); // 匹配分钟（mm）
	QRegExp secondRx("s+"); // 匹配秒（ss）

	int pos = 0;
	while (pos < m_format.length())
	{
		if (yearRx.indexIn(m_format, pos) == pos)
		{
			addSection(CxiDateTimePicker::DateTimeSection::Year, pos, yearRx.matchedLength());
			pos += yearRx.matchedLength();
		}
		else if (monthRx.indexIn(m_format, pos) == pos)
		{
			addSection(CxiDateTimePicker::DateTimeSection::Month, pos, monthRx.matchedLength());
			pos += monthRx.matchedLength();
		}
		else if (dayRx.indexIn(m_format, pos) == pos)
		{
			addSection(CxiDateTimePicker::DateTimeSection::Day, pos, dayRx.matchedLength());
			pos += dayRx.matchedLength();
		}
		else if (hourRx.indexIn(m_format, pos) == pos)
		{
			addSection(CxiDateTimePicker::DateTimeSection::Hour, pos, hourRx.matchedLength());
			pos += hourRx.matchedLength();
		}
		else if (minuteRx.indexIn(m_format, pos) == pos)
		{
			addSection(CxiDateTimePicker::DateTimeSection::Minute, pos, minuteRx.matchedLength());
			pos += minuteRx.matchedLength();
		}
		else if (secondRx.indexIn(m_format, pos) == pos)
		{
			addSection(CxiDateTimePicker::DateTimeSection::Second, pos, secondRx.matchedLength());
			pos += secondRx.matchedLength();
		}
		else
		{
			pos++;// 跳过分隔符（如"-"、":"）
		}
	}
	// 从当前文本更新各Section的值
	updateSectionsFromText();
}
//添加分段
void CxiDateTimePickerPrivate::addSection(CxiDateTimePicker::DateTimeSection type, int start, int length)
{
	Section s{};
	s.type = type;
	s.start = start;
	s.length = length;
	s.value = 0;
	m_sections.append(s);
}
//从文本更新分段值
void CxiDateTimePickerPrivate::updateSectionsFromText()
{
	Q_Q(CxiDateTimePicker);
	QString text = q->text();
	for (auto& s: m_sections)
	{
		if (s.start + s.length > text.length()) continue;
		QString valStr = text.mid(s.start, s.length);
		s.value = valStr.toInt();
	}
}
//从分段值更新文本
void CxiDateTimePickerPrivate::updateTextFromSections()
{
	Q_Q(CxiDateTimePicker);
	QString text = m_format;// 以格式为模板替换Section值
	for (const auto& s: m_sections)
	{
		// 格式化数值（如月份补0为2位）
		QString valStr = QString("%1").arg(s.value, s.length, 10, QChar('0'));
		text.replace(s.start, s.length, valStr);
	}
	q->setText(text);
	selectCurrentSection();// 保持选中状态
}
//获取当前光标所在的分段
CxiDateTimePicker::DateTimeSection CxiDateTimePickerPrivate::sectionAtCursor()
{
	Q_Q(CxiDateTimePicker);
	int cursorPos = q->cursorPosition();
	for (const auto& s: m_sections)
	{
		if (cursorPos >= s.start && cursorPos < s.start + s.length)
		{
			return s.type;
		}
	}
	return CxiDateTimePicker::DateTimeSection::None;
}
//选中当前分段
void CxiDateTimePickerPrivate::selectCurrentSection()
{
	Q_Q(CxiDateTimePicker);
	for (const auto& s: m_sections)
	{
		if (s.type == m_currentSection)
		{
			q->setSelection(s.start, s.length);
			break;
		}
	}
}
//调整分段值
void CxiDateTimePickerPrivate::adjustSectionValue(CxiDateTimePicker::DateTimeSection section, int delta)
{
	// 先从当前文本同步最新值（防止手动修改后未更新）
	updateSectionsFromText();

	// 找到目标Section并调整值
	for (auto& s: m_sections)
	{
		if (s.type != section) continue;

		//LOG_INFO("修改前：", s.value, " " + section2String(s.type));
		switch (section)
		{
		case CxiDateTimePicker::DateTimeSection::Year:
			s.value += delta;
			// 年份无严格边界，可根据需求限制（如1900-2100）
			s.value = qBound(1900, s.value, 2100);
			break;
		case CxiDateTimePicker::DateTimeSection::Month:
			s.value += delta;
			// 月份循环（1-12）
			if (s.value < 1) s.value = 12;
			else if (s.value > 12)
				s.value = 1;
			break;
		case CxiDateTimePicker::DateTimeSection::Day: {
			// 先获取当前年和月，确保日期合法
			int year = getSectionValue(CxiDateTimePicker::DateTimeSection::Year);
			int month = getSectionValue(CxiDateTimePicker::DateTimeSection::Month);
			// 如果没有年，假设是闰年（2月有29天）
			if (year <= 0) year = 2024;// 闰年
			// 如果没有月，假设是31天的月
			if (month <= 0) month = 1;
			int maxDay = QDate(year, month, 1).daysInMonth();// 当月最大天数
			s.value += delta;
			s.value = qBound(1, s.value, maxDay);
			break;
		}
		case CxiDateTimePicker::DateTimeSection::Hour: {
			// 判断是12小时制还是24小时制（根据格式中的HH/hh判断）
			bool is24Hour = (m_format.contains("HH"));
			if (is24Hour)
			{
				// 24小时制：0-23，超出后循环
				s.value += delta;
				if (s.value < 0) s.value += 24;
				else if (s.value >= 24)
					s.value %= 24;
			}
			else
			{
				// 12小时制：1-12，配合AM/PM（此处假设已处理上下午切换逻辑）
				s.value += delta;
				if (s.value < 1) s.value = 12;
				else if (s.value > 12)
					s.value = 1;
				// 注意：实际使用中需同步处理AM/PM切换，例如12点加1小时变为1点并切换上下午
			}
			break;
		}
		case CxiDateTimePicker::DateTimeSection::Minute:
			s.value += delta;
			// 分钟：0-59，超出后循环
			if (s.value < 0) s.value += 60;
			else if (s.value >= 60)
				s.value %= 60;
			break;
		case CxiDateTimePicker::DateTimeSection::Second:
			s.value += delta;
			// 秒：0-59，超出后循环
			if (s.value < 0) s.value += 60;
			else if (s.value >= 60)
				s.value %= 60;
			break;
		default:
			break;
		}
		//LOG_INFO("修改后：", s.value, " " + section2String(s.type));
		break;
	}
	// 更新显示
	updateTextFromSections();
}
//获取指定分段的值
int CxiDateTimePickerPrivate::getSectionValue(CxiDateTimePicker::DateTimeSection section)
{
	for (const auto& s: m_sections)
	{
		if (s.type == section)
		{
			return s.value;
		}
	}
	return 0;// 未找到时返回默认值
}
//输入验证，成功后进行分段赋值
void CxiDateTimePickerPrivate::validateInput()
{
	Q_Q(CxiDateTimePicker);
	QString currentText = q->text();
	//尝试用当前格式解析输入文本
	currentText = DateTimeParser::parseDateTimeSmart(currentText, m_format);
	QDateTime parsed = QDateTime::fromString(currentText, m_format);

	if (parsed.isValid() || currentText.isEmpty())
	{
		m_validText = currentText;
		q->setText(currentText);
		parseSections();
	}
	else
	{
		// 解析失败：恢复上一次有效文本
		q->setText(m_validText);
	}
}